import axios from "axios";

axios.defaults.headers.post["Content-Type"] = "application/json";

const toLogin = async () => {
  const microApp = (window as any).__MicroAPP__;
  if (microApp) {
    microApp.bus.$emit({
      eventName: microApp.keys.UserLogin,
    });
  }
};

axios.interceptors.request.use(
  (config) => {
    const token = (window as any).__MicroAPP__?.user?.token;
    if (token) {
      (config.headers as any) = {
        ...(config.headers || {}),
        Authorization: `Bearer ${token}`,
      };
    }
    return config;
  },
  (error) => Promise.reject(error)
);

axios.interceptors.response.use(
  (response) => {
    const { data } = response;
    if (data != null && data.code === -2) {
      toLogin();
    }
    return data;
  },
  (error) => {
    const status = error?.response?.status;
    const data = error?.response?.data;
    if (status === 401 || status === 403 || (data != null && data.code === -2)) {
      toLogin();
    }
    return Promise.reject(error);
  }
);

/** 判断是否普通对象*/
function isPlainObject(v: any) {
  return Object.prototype.toString.call(v) === "[object Object]";
}

const factory = (obj: any) => {
  const output: any = {};

  Object.keys(obj).forEach((methodKey) => {
    Object.keys(obj[methodKey]).forEach((apiKey: string) => {
      const rawUrl = obj[methodKey][apiKey];

      output[apiKey] = function (data: any = {}, args?: any, cb?: any) {
        //  处理路径占位符 :xxx
        let url: string = rawUrl;
        const matches = typeof url === "string" ? url.match(/:[a-zA-Z_]\w*/g) || [] : [];
        const usedKeys = new Set<string>();

        matches.forEach((m) => {
          const key = m.slice(1); // 去掉前面的冒号
          const val = data?.[key] ?? "";
          usedKeys.add(key);
          url = url.replace(new RegExp(m, "g"), encodeURIComponent(String(val)));
        });

        // 把“没有参与路径替换”的字段作为 query params
        const cleanParams: any = {};
        if (isPlainObject(data)) {
          Object.keys(data).forEach((k) => {
            if (!usedKeys.has(k)) {
              const v = data[k];
              cleanParams[k] = isPlainObject(v) ? JSON.stringify(v) : v;
            }
          });
        }

        // 组装 axios 选项
        const common: any = {
          signal: args?.controller?.signal,
          ...(args?.timeout ? { timeout: args.timeout } : {}),
        };

        switch (methodKey) {
          case "get": {
            if (Object.keys(cleanParams).length > 0) {
              return axios.get(url, { ...common, params: cleanParams });
            }
            return axios.get(url, { ...common });
          }
          case "post":
            return axios.post(url, data, { ...args, ...common });
          case "delete":
            return axios.delete(url, { ...common, data });
          case "file":
            return axios.post(url, data, {
              headers: {
                "content-type": "multipart/form-data",
                ...(args?.headers || {}),
              },
              onUploadProgress: cb,
              ...common,
            });
          default:
            return null;
        }
      };
    });
  });

  return output;
};

export default factory;
